package com.sky.service.impl;

import com.sky.dto.GoodsSalesDTO;
import com.sky.mapper.OrderMapper;
import com.sky.mapper.UserMapper;
import com.sky.service.StatisticsService;
import com.sky.service.WorkspaceService;
import com.sky.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.xmlbeans.ResourceLoader;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.ArrayList;
import java.util.List;

@Service
@Slf4j
public class StatisticsServiceImpl implements StatisticsService
{
    @Autowired
//    private StatisticsMapper statisticsMapper;
private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private WorkspaceService workspaceService;
//    @Autowired
//    private OrderDetailMapper orderDetailmapper;
    @Override
    public TurnoverReportVO turnoverStatistics(LocalDate begin, LocalDate end)
    {
        //判断localdate类型的begin不能大于end
        if(begin.isAfter(end))throw new RuntimeException("开始时间不能大于结束时间");
        if(begin==null || end==null) throw new RuntimeException("时间不能为空");

        TurnoverReportVO turnoverReportVO=new TurnoverReportVO();
        List<LocalDate> dateList=new ArrayList<>();
        List<Double> turnoverList=new ArrayList<>();
        dateList.add(begin);
        //用java代码构造datelist
        while (!begin.equals(end))
        {
            begin = begin.plusDays(1);
            dateList.add(begin);
//            System.out.println("******************************");
        }

        for(LocalDate date : dateList)
        {//将当前天的0点0分0秒和23.59,59分传入到方法中，目标类型的localdatetime
//            System.out.println("今天的日期是："+date);
            LocalDateTime time1 = LocalDateTime.of(date, LocalTime.MIN);//一条中最小的时刻0点0分0秒
            LocalDateTime time2 = LocalDateTime.of(date, LocalTime.MAX);
            Double amount = orderMapper.getAmountByLocalDate(time1, time2);
//            System.out.println(time1+""+time2+""+"今天的营业额是"+amount);


            if(amount==null)//如果为null，表示当天营业额为0，不能统计金额的集合中添加null把，这样不就违背自身的意思了么，所以是null旧赋值成0
            {
                amount = 0D;//跟0.0表示的意思一样。表示这是double的0
                turnoverList.add(amount);
            }
            else  turnoverList.add(amount);
        }

        String join = StringUtils.join(dateList, ",");
        String join1 = StringUtils.join(turnoverList, ",");
        turnoverReportVO.setDateList(join);
        turnoverReportVO.setTurnoverList(join1);





return turnoverReportVO;

//        select amount from orders where order_time gt; begin lt; end and status=5

        //然后sql遍历datelist，统计每一天的已完成金额




    }

    @Override
    public UserReportVO userStatistics(LocalDate begin, LocalDate end)
    {
        if (begin.isAfter(end)) throw new RuntimeException("开始时间不能大于结束时间");
        if (begin == null || end == null) throw new RuntimeException("时间不能为空");
        UserReportVO userReportVO = new UserReportVO();
        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> totalUserList = new ArrayList<>();//截至某一天用户数总量
        List<Integer> newUserList = new ArrayList<>();//每天新增的用户数
        dateList.add(begin);
        //用java代码构造datelist
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
//            System.out.println("******************************");
        }
        Integer yesterdayUserTotal =0;//记录前一天用户的总量
        for(LocalDate date :dateList)//每一天新用户数量，和某一天之前（饱含这一天）总的用户数量(截至某一天之前的所有用户数量)
        {
//            尝试优化一下，第二天的新增用户就是第二天用户总数-第一天用户总数，少进行io操作

            LocalDateTime time1 = LocalDateTime.of(date, LocalTime.MIN);//一条中最小的时刻0点0分0秒
            LocalDateTime time2 = LocalDateTime.of(date, LocalTime.MAX);//一条中最大的时刻23.59,59分
            Integer totalUserSum = userMapper.getSumUserByLocalDate(null, time2);
            /**
             * 我这样写一直是调用截至time2之前（包含time2）用户总数，
             * 我的唯一一条是数据是3月份建立的，而time2默认是近七天就是4月1开始.也就是说第一次执行就是截至4月1之前的用户总数那当然为1，第二次执行是4月2之前的用户总数第三次执行是4月3之前的用户总数
             * 这样就会导致我的新增用户数量一直为0（通过后一天减前一天的用户总数算的），其实没办法totalUserList算的就是截至某一天之前的所有用户数量，那这种情况没办法
             * 老师的是登录user表的第一条数据创建时间是在七天内（也就是说写到这个地方，距离他第一天数据不到七天，那么近七天的范围就会包括user表第一条数据的创建时间）
             * 我是登录user表的第一条数据创建时间是在七天外（也就是说写到这个地方，距离我第一天数据超过了七天，那么近七天的范围就不会包括user表第一条数据的创建时间）导致，查询近七天的第一天的截至用户总数就可以拿到唯一的一个用户总数，剩余几天由于没有新增用户，
             * 导致查询的效果跟,查询第一天的截至用户总数,效果差不多
             *
             */
            yesterdayUserTotal =totalUserSum;

//            System.out.println("totalUserSum的数值："+totalUserSum);
//            System.out.println("yesterdayUserTotal的数值："+yesterdayUserTotal);
            Integer newUserSum=totalUserSum- yesterdayUserTotal;
            //调试一下totalUserSum和yesterdayUserTotal

//            Integer newUserSum =userMapper.getSumUserByLocalDate(time1, time2);
            newUserSum = newUserSum ==null? newUserSum =0: newUserSum;
            newUserList.add(newUserSum);
            totalUserList.add(totalUserSum);


//            LocalDateTime time1 = LocalDateTime.of(date, LocalTime.MIN);//一条中最小的时刻0点0分0秒
//            LocalDateTime time2 = LocalDateTime.of(date, LocalTime.MAX);//一条中最大的时刻23.59,59分
//            Integer totalUserSum = userMapper.getSumUserByLocalDate(null, time2);
//            Integer newUserSum =userMapper.getSumUserByLocalDate(time1, time2);
//            newUserSum = newUserSum ==null? newUserSum =0: newUserSum;
//            newUserList.add(newUserSum);
//            totalUserList.add(totalUserSum);

        }


        userReportVO.setDateList(StringUtils.join(dateList, ","));
        userReportVO.setNewUserList(StringUtils.join(newUserList, ","));
        userReportVO.setTotalUserList(StringUtils.join(totalUserList, ","));

        return userReportVO;




    }

    @Override
    public OrderReportVO ordersStatistics(LocalDate begin, LocalDate end) {
        if (begin.isAfter(end)) throw new RuntimeException("开始时间不能大于结束时间");
        if (begin == null || end == null) throw new RuntimeException("时间不能为空");
        OrderReportVO orderReportVO = new OrderReportVO();
        List<LocalDate> dateList = new ArrayList<>();
        List<Integer> orderCountList = new ArrayList<>();
        List<Integer> validOrderCountList = new ArrayList<>();

        dateList.add(begin);
        //用java代码构造datelist
        while (!begin.equals(end)) {
            begin = begin.plusDays(1);
            dateList.add(begin);
          //  System.out.println("******************************");
        }
//        System.out.println("日期列表："+dateList);

        //        构造每天有效订单数列表
        for(LocalDate date :dateList)//构造每天订单数量列表
        {
            LocalDateTime time1 = LocalDateTime.of(date, LocalTime.MIN);//一条中最小的时刻0点0分0秒
            LocalDateTime time2 = LocalDateTime.of(date, LocalTime.MAX);//一条中最大的时刻23.59,59分
            Integer orderCount =orderMapper.countSumByLocalDate(time1, time2);//每天订单总数
            Integer validOrderConut = orderMapper.countValidOrderCountByLocalDate(time1, time2);//每天有效订单数
            if(orderCount==null) orderCount=0;
            if(validOrderConut==null) validOrderConut=0;
            orderCountList.add(orderCount);
            validOrderCountList.add(validOrderConut);
        }
//        System.out.println("每天订单列表"+orderCountList);
//        System.out.println("每天有效订单列表"+validOrderCountList);


        //截至到时间区间内的的订单总数
        Integer orderCountSum =0;

        for(Integer orderCount1:orderCountList){orderCountSum +=orderCount1;}
//        System.out.println("订单总数"+orderCountSum);
//      有效订单数
        Integer validOrderCount=0;
        for(Integer validOrderCount1 :validOrderCountList){validOrderCount += validOrderCount1;}
//        System.out.println("有效订单数"+validOrderCount);
        //订单完成率
        Double orderCompletionRate=0d;
        if (orderCountSum!=null){ orderCompletionRate =validOrderCount.doubleValue()/orderCountSum;}
//        System.out.println("订单完成率"+orderCompletionRate);


        String join1 = StringUtils.join(dateList, ",");
        String join2 = StringUtils.join(orderCountList, ",");
        String join3 = StringUtils.join(validOrderCountList, ",");

        orderReportVO.setDateList(join1);//日期列表
        orderReportVO.setOrderCountList(join2);//订单数列表
        orderReportVO.setValidOrderCountList(join3);//有效订单数列表

        orderReportVO.setTotalOrderCount(orderCountSum);//订单总数
        orderReportVO.setOrderCompletionRate(orderCompletionRate);//订单完成率
        orderReportVO.setValidOrderCount(validOrderCount);//有效订单数
//        log.info("看看{}",orderReportVO);



        return orderReportVO;
    }

    @Override
    public SalesTop10ReportVO top10(LocalDate begin, LocalDate end) {
        SalesTop10ReportVO salesTop10ReportVO = new SalesTop10ReportVO();
        LocalDateTime time1 = LocalDateTime.of(begin, LocalTime.MIN);//第一天的最小的时刻0点0分0秒
        LocalDateTime time2 = LocalDateTime.of(end, LocalTime.MAX);//最后一天的最大的时刻23.59,59分

        List<GoodsSalesDTO> top10NamesAndNumbersByLocalDate = orderMapper.getTop10NamesAndNumbersByLocalDate(time1, time2);

        log.info("看看enen{}",top10NamesAndNumbersByLocalDate);
        List<String> Names = new ArrayList<>();
        List<Integer> Numbers = new ArrayList<>();
        for(GoodsSalesDTO goodsSalesDTO:top10NamesAndNumbersByLocalDate)
        {
            Names.add(goodsSalesDTO.getName());
            Numbers.add(goodsSalesDTO.getNumber());
        }
        salesTop10ReportVO.setNameList(StringUtils.join(Names, ","));
        salesTop10ReportVO.setNumberList(StringUtils.join(Numbers, ","));
        log.info("看看{}",salesTop10ReportVO);
        return salesTop10ReportVO;
        //尝试把Map的key和value分别放在两个list中

//        for( Map<String, String> map :top10NamesAndNumbersByLocalDate)
//        {
//            for (Map.Entry<String, String> entry : map.entrySet())
//            {
//                String key = entry.getKey();
//                String value = entry.getValue();
//                Names.add(key);
//                Numbers.add(value);
//            }
//
//        }



//        for (Map.Entry<String, Integer> entry : top10NamesAndNumbersByLocalDate.entrySet()) {
//            Names.add(entry.getKey());
//            Numbers.add(entry.getValue());
//        }
//        System.out.println("名字："+Names);
//        System.out.println("销量："+Numbers);
////        //因为orderdetail并没有每个商品对应的下单时间，我要通过order查出来试试
////        List<String> Names = orderDetailmapper.GetTop10NameByLocalDate(time1, time2);
////        List<Integer> Numbers = orderDetailmapper.GetTop10NumberByLocalDate(time1, time2);
//
//



    }

    @Override
    public void exportBusinessData(HttpServletResponse response) {

//       FileInputStream fis = new FileInputStream("sky-server/src/main/resources/template/info.xlsx");

// 拿到模板文件
       InputStream fis1 =this.getClass().getClassLoader().getResourceAsStream("/template/info.xlsx");
        InputStream fis = ResourceLoader.class.getResourceAsStream("/template/info.xlsx");
//拿到近三十天的日期
       LocalDate dateBegin = LocalDate.now();dateBegin = dateBegin.plusMonths(-1);//上个月同一天，这里创建了新的对象，让他重新保存了新对象的地址
        LocalDate dateEnd = LocalDate.now().plusDays(-1);//昨天
        LocalDateTime time1 = LocalDateTime.of(dateBegin, LocalTime.MIN);//一个月前的那一天的的最小的时刻0点0分0秒
        LocalDateTime time2 = LocalDateTime.of(dateEnd, LocalTime.MAX);//昨天最大的时刻23.59,59分

//查询数据库获取近三十天的运营的概览数据
        BusinessDataVO businessData = workspaceService.getBusinessData(time1, time2);
 //读取模板文件，并通过Apache POI将数据写入
        try {
            XSSFWorkbook excel = new XSSFWorkbook(fis);
            //数据写入
            XSSFSheet sheet = excel.getSheet("Sheet1");
              sheet.getRow(1).getCell(1).setCellValue("时间： "+ dateBegin + "至" + dateEnd);
              sheet.getRow(3).getCell(2).setCellValue(businessData.getTurnover());
              sheet.getRow(3).getCell(4).setCellValue(businessData.getOrderCompletionRate());
              sheet.getRow(3).getCell(6).setCellValue(businessData.getNewUsers());
              sheet.getRow(4).getCell(2).setCellValue(businessData.getValidOrderCount());
              sheet.getRow(4).getCell(4).setCellValue(businessData.getUnitPrice());
//填充excel所需要的明细数据
            LocalDate date = dateBegin.plusDays(-1);
            int currentRow =7;
            for(int i=0;i<30;i++)
            {   date=date.plusDays(1);//把新new的对象重新赋值给date，大部分类型都是不可变的
                BusinessDataVO businessData1 = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));

                System.out.println("一个月前的那一天："+dateBegin);
                System.out.println("一个月前的那一天+1："+date);
                //某一天的营业数据

                XSSFRow row = sheet.getRow(currentRow);
                row.getCell(1).setCellValue(String.valueOf(date));
                row.getCell(2).setCellValue(businessData1.getTurnover());
                row.getCell(3).setCellValue(businessData1.getValidOrderCount());
                row.getCell(4).setCellValue(businessData1.getOrderCompletionRate());
                row.getCell(5).setCellValue(businessData1.getUnitPrice());
                row.getCell(6).setCellValue(businessData1.getNewUsers());
                currentRow++;
            }

//              int currentRow =7;
//              for(int i=0;i<30;i++)
//              {
//                  LocalDate date = dateBegin.plusDays(1);
//                  System.out.println("一个月前的那一天："+dateBegin);
//                  System.out.println("一个月前的那一天+1："+date);
//                  //某一天的营业数据
//                  BusinessDataVO businessData1 = workspaceService.getBusinessData(LocalDateTime.of(date, LocalTime.MIN), LocalDateTime.of(date, LocalTime.MAX));
//                  XSSFRow row = sheet.getRow(currentRow);
//                  row.getCell(1).setCellValue(String.valueOf(date));
//                  row.getCell(2).setCellValue(businessData1.getTurnover());
//                  row.getCell(3).setCellValue(businessData1.getValidOrderCount());
//                  row.getCell(4).setCellValue(businessData1.getOrderCompletionRate());
//                  row.getCell(5).setCellValue(businessData1.getUnitPrice());
//                  row.getCell(6).setCellValue(businessData1.getNewUsers());
//                      currentRow++;
//              }

            ServletOutputStream outputStream = response.getOutputStream();
            excel.write(outputStream);
//资源关闭
            excel.close();
            outputStream.close();
            fis.close();

        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }

    }
}
